package l2hc.gameserver.model.entity;

import java.util.ArrayList;

import l2hc.commons.util.Rnd;
import l2hc.gameserver.ThreadPoolManager;
import l2hc.gameserver.instancemanager.UnderGroundColliseumManager;
import l2hc.gameserver.model.Party;
import l2hc.gameserver.model.Player;
import l2hc.gameserver.model.Zone;
import l2hc.gameserver.model.base.TeamType;
import l2hc.gameserver.network.serverpackets.SystemMessage;
import l2hc.gameserver.utils.Location;
import l2hc.gameserver.utils.ReflectionUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Coliseum
{
  private static final Logger _log = LoggerFactory.getLogger(Coliseum.class);

  private Party previusWinners = null;
  private boolean isWaitingRoom1Free = true;
  private boolean isWaitingRoom2Free = true;
  private boolean isInUse;
  private int winCount = 0;
  private Party partyInRoom1 = null;
  private Party partyInRoom2 = null;
  private int minlevel;
  private int maxlevel;
  @SuppressWarnings({ "unchecked", "rawtypes" })
private ArrayList<Party> party_waiting_list = new ArrayList();
  @SuppressWarnings({ "unchecked", "rawtypes" })
private ArrayList<Party> party_inbattle_list = new ArrayList();
  private Zone _zone;
  private static Integer _event_cycle = Integer.valueOf(0);
  private int _id = 0;

  public int getMinLevel()
  {
    return this.minlevel;
  }

  public int getMaxLevel()
  {
    return this.maxlevel;
  }

  private boolean checkOffline(Party party)
  {
    this.party_waiting_list.add(party);
    return party.getMemberCount() == 0;
  }

  public Coliseum()
  {
    this._id += 1;
    this.minlevel = 1;
    this.maxlevel = 85;
    try
    {
      load();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    if (_event_cycle.intValue() == 0)
      init();
  }

  public int getId()
  {
    return this._id;
  }

  @SuppressWarnings("unused")
private void load()
  {
    _event_cycle = Integer.valueOf(getColiseumMatchNumber());
    Integer localInteger1;
    if (_event_cycle.intValue() == 2147483647) {
      _event_cycle = Integer.valueOf(1);
    } else {
      localInteger1 = _event_cycle; Integer localInteger2 = Coliseum._event_cycle = Integer.valueOf(_event_cycle.intValue() + 1);
    }
  }

  private void init() {
    setcoliseummatchnumber(1);
  }

  private void startBattle(Party party, Party party2)
  {
    if (!isInUse())
    {
      if (getPreviusWinners() == null) {
        ThreadPoolManager.getInstance().schedule(new StartBattle(party, party2), 10000L);
      }
      else {
        ThreadPoolManager.getInstance().schedule(new StartBattle(party, getPreviusWinners()), 10000L);
        setIsWaitingRoom1Free(true);
        Location teleloc = getFreeWaitingRoom();
        setIsWaitingRoom2Free(true);
        teleportToWaitingRoom(party2, teleloc);
      }
    }
    else
      ThreadPoolManager.getInstance().schedule(new TryStart(party, party2), 300000L);
  }

  public static void register(Player player, int minLevel, int maxLevel)
  {
    Coliseum coli = UnderGroundColliseumManager.getInstance().getColiseumByLevelLimit(maxLevel);
    if (coli == null)
    {
      player.sendMessage("this is not work now, if you have any information about it, contact as");
      return;
    }
    Location teleloc = coli.getFreeWaitingRoom();
    if (teleloc == null) {
      player.sendMessage("this is not work now, if you have any information about it, contact as");
    }
    coli.party_waiting_list.add(player.getParty());
    coli.teleportToWaitingRoom(player.getParty(), teleloc);
  }

  public void teleportToWaitingRoom(Party party, Location teleloc)
  {
    if (isWaitingRoom1Free())
    {
      setIsWaitingRoom1Free(false);
      setPartyInRoom1(party);
    }
    else if (isWaitingRoom2Free())
    {
      setIsWaitingRoom2Free(false);
      setPartyInRoom2(party);
    }
    else
    {
      party.getPartyLeader().sendMessage("rooms are not free you has been registred try to use teleport function later");
      return;
    }
    for (Player member : party.getPartyMembers())
      member.teleToLocation(teleloc);
    if (!this.isWaitingRoom2Free)
      startBattle(getPartyInRoom1(), getPartyInRoom2());
  }

  public Location getFreeWaitingRoom()
  {
    if (isWaitingRoom1Free())
      return this._zone.getRestartPoints().get(0);
    if (isWaitingRoom2Free()) {
      return this._zone.getRestartPoints().get(1);
    }
    return null;
  }

  public int getColiseumMatchNumber()
  {
    return _event_cycle.intValue();
  }

  public void setcoliseummatchnumber(int number)
  {
    _event_cycle = Integer.valueOf(number);
  }

  public boolean checkIfInZone(int x, int y)
  {
    return getZone().checkIfInZone(x, y);
  }

  public final Zone getZone()
  {
    if (this._zone == null)
      this._zone = ReflectionUtils.getZone("UnderGroundColiseum");
    return this._zone;
  }

  public void StopBattle(Party party, Party party2, TeamType winner, long period)
  {
    ThreadPoolManager.getInstance().schedule(new StopBattle(party, party2, winner), period);
  }

  public void teleportPlayers(Party party, Party party2)
  {
    if (((party == null) && (party2 == null)) || ((party2 == null) && (party != null) && (party.getPartyMembers().isEmpty())) || ((party == null) && (party2 != null) && (party2.getPartyMembers().isEmpty())) || ((party2 != null) && (party != null) && (party.getPartyMembers().isEmpty()) && (party2.getPartyMembers().isEmpty())))
    {
      StopBattle(party, party2, TeamType.NONE, 20000L);
      this.party_inbattle_list.remove(party);
      this.party_inbattle_list.remove(party2);
    }
    if ((party2 != null) && ((party == null) || (party.getPartyMembers().isEmpty())))
    {
      StopBattle(party, party2, party2.getPartyLeader().getTeam(), 20000L);
      this.party_inbattle_list.remove(party);
    }
    else if ((party != null) && ((party2 == null) || (party2.getPartyMembers().isEmpty())))
    {
      StopBattle(party, party2, party.getPartyLeader().getTeam(), 20000L);
      this.party_inbattle_list.remove(party2);
    }
    else
    {
      if (party != null)
      {
        for (Player member : party.getPartyMembers())
        {
          member.setTeam(TeamType.BLUE);

          Location locOnBGToTP = this._zone.getRestartPoints().get(3);
          member.teleToLocation(locOnBGToTP);
        }
      }
      if (party2 != null)
      {
        for (Player member : party2.getPartyMembers())
        {
          member.setTeam(TeamType.RED);
          Location locOnBGToTP = this._zone.getRestartPoints().get(4);
          member.teleToLocation(locOnBGToTP);
        }
      }
    }
  }

  public void setPreviusWinner(Party previusWinners)
  {
    this.previusWinners = previusWinners;
  }

  public Party getPreviusWinners()
  {
    return this.previusWinners;
  }

  public void setIsWaitingRoom1Free(boolean isWaitingRoom1Free)
  {
    this.isWaitingRoom1Free = isWaitingRoom1Free;
  }

  public boolean isWaitingRoom1Free()
  {
    return this.isWaitingRoom1Free;
  }

  public void setIsWaitingRoom2Free(boolean isWaitingRoom2Free)
  {
    this.isWaitingRoom2Free = isWaitingRoom2Free;
  }

  public boolean isWaitingRoom2Free()
  {
    return this.isWaitingRoom2Free;
  }

  public void setIsInUse(boolean isInUse)
  {
    this.isInUse = isInUse;
  }

  public boolean isInUse()
  {
    return this.isInUse;
  }

  public ArrayList<Party> getPartysInBattleGround()
  {
    return this.party_inbattle_list;
  }

  public ArrayList<Party> getWaitingPartys()
  {
    return this.party_waiting_list;
  }

  public void setWinCount(int winCount)
  {
    this.winCount = winCount;
  }

  public void incWinCount()
  {
    this.winCount += 1;
  }

  public int getWinCount()
  {
    return this.winCount;
  }

  public Party getPartyInRoom1()
  {
    return this.partyInRoom1;
  }

  public Party getPartyInRoom2()
  {
    return this.partyInRoom2;
  }

  public void setPartyInRoom1(Party p1)
  {
    this.partyInRoom1 = p1;
  }

  public void setPartyInRoom2(Party p2)
  {
    this.partyInRoom2 = p2;
  }

  public class StartBattle
    implements Runnable
  {
    int _number;
    Party _party1;
    Party _party2;

    public StartBattle(Party party, Party party2)
    {
      this._number = Coliseum.this.getColiseumMatchNumber();
      this._party1 = party;
      this._party2 = party2;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
	public void run()
    {
      Coliseum.this.party_waiting_list.remove(this._party1);
      Coliseum.this.party_waiting_list.remove(this._party2);
      if ((Coliseum.this.getPartyInRoom1().equals(this._party1)) || (Coliseum.this.getPartyInRoom1().equals(this._party2)))
        Coliseum.this.setPartyInRoom1(null);
      if ((Coliseum.this.getPartyInRoom2().equals(this._party1)) || (Coliseum.this.getPartyInRoom2().equals(this._party2))) {
        Coliseum.this.setPartyInRoom2(null);
      }
      boolean isParty1Ready = Coliseum.this.checkOffline(this._party1);
      boolean isParty2Ready = Coliseum.this.checkOffline(this._party2);
      if (!isParty1Ready)
      {
        Coliseum.this.party_waiting_list.remove(this._party1);
        Coliseum.this.setIsWaitingRoom1Free(true);
        this._party2.broadcastMessageToPartyMembers("opponents party is offline, wait for next opponent");
        return;
      }
      if (!isParty2Ready)
      {
        Coliseum.this.party_waiting_list.remove(this._party2);
        Coliseum.this.setIsWaitingRoom2Free(true);
        this._party1.broadcastMessageToPartyMembers("opponents party is offline, wait for next opponent");
        return;
      }

      Coliseum.this.party_inbattle_list.addAll(Coliseum.this.party_waiting_list);
      Coliseum.this.party_waiting_list.remove(this._party2);
      Coliseum.this.party_waiting_list.remove(this._party1);
      Coliseum.this.setIsWaitingRoom1Free(true);
      Coliseum.this.setIsWaitingRoom2Free(true);
      Coliseum.this.teleportPlayers(this._party1, this._party2);
      Coliseum.this.setIsInUse(true);
      Party next;
      if (Coliseum.this.party_waiting_list.size() > 0)
      {
        ArrayList toDel = new ArrayList();
        for (Party party : Coliseum.this.party_waiting_list)
        {
          if (party.getPartyMembers().size() > 6)
            party.broadcastMessageToPartyMembers("Free room at coliseum append");
          else
            toDel.add(party);
        }
        //TODO
      /*  for (Party party : toDel)
        {
          party.broadcastMessageToPartyMembers("conditions are nor right for Undergorund battle try register later");
          Coliseum.this.party_waiting_list.remove(party);
        }*/
        if (Coliseum.this.party_waiting_list.size() == 0) {
          return;
        }
        next = Coliseum.this.party_waiting_list.get(Rnd.get(Coliseum.this.party_waiting_list.size() - 1));
        for (Player member : next.getPartyMembers())
        {
          if ((member.getLevel() > Coliseum.this.getMaxLevel()) || (member.getLevel() < Coliseum.this.getMinLevel()))
          {
            next.broadcastToPartyMembers(member, new SystemMessage(2097).addName(member));
            return;
          }
          if (member.isCursedWeaponEquipped())
          {
            next.broadcastToPartyMembers(member, new SystemMessage(2098).addName(member));
            return;
          }
          Location teleloc = Coliseum.this.getFreeWaitingRoom();
          if (teleloc == null)
          {
            Coliseum._log.info("bug cannot find teleloc for coliseum id: " + Coliseum.this.getId(), "UC");
            return;
          }
          Coliseum.this.teleportToWaitingRoom(next, teleloc);
        }
        if (Coliseum.this.party_waiting_list.size() < 2) {
          return;
        }
        Party next2 = Coliseum.this.party_waiting_list.get(Rnd.get(Coliseum.this.party_waiting_list.size() - 1));
        while (next2 == next)
        {
          next2 = Coliseum.this.party_waiting_list.get(Rnd.get(Coliseum.this.party_waiting_list.size() - 1));
        }
        next = next2;
        for (Player member : next.getPartyMembers())
        {
          if ((member.getLevel() > Coliseum.this.getMaxLevel()) || (member.getLevel() < Coliseum.this.getMinLevel()))
          {
            next.broadcastToPartyMembers(member, new SystemMessage(2097).addName(member));
            return;
          }
          Location teleloc = Coliseum.this.getFreeWaitingRoom();
          if (teleloc == null)
          {
            Coliseum._log.info("bug cannot find teleloc for coliseum id: " + Coliseum.this.getId(), "UC");
            return;
          }
          Coliseum.this.teleportToWaitingRoom(next, teleloc);
        }
      }
    }
  }

  public class StopBattle
    implements Runnable
  {
    Party _party1;
    Party _party2;
    TeamType _winner = TeamType.NONE;

    public StopBattle(Party party, Party party2, TeamType winner)
    {
      this._party1 = party;
      this._party2 = party2;
      this._winner = winner;
    }

    public void run()
    {
      Coliseum.this.party_inbattle_list.remove(this._party1);
      Coliseum.this.party_inbattle_list.remove(this._party2);
      if (this._winner == TeamType.NONE)
      {
        Coliseum.this.setPreviusWinner(null);
        Coliseum.this.setWinCount(0);
      }
      else
      {
        if (this._party1.getPartyLeader().getTeam() == this._winner)
        {
          if (!Coliseum.this.getPreviusWinners().equals(this._party1))
          {
            Coliseum.this.setPreviusWinner(this._party1);
            Coliseum.this.setWinCount(1);
            for (Player member : this._party1.getPartyMembers())
              member.setFame(member.getFame() + 80, "Coliseum");
          }
          else
          {
            Coliseum.this.incWinCount();
            for (Player member : this._party1.getPartyMembers())
              member.setFame(member.getFame() + 80 + Coliseum.this.getWinCount() * 5, "Coliseum");
          }
          Location teleloc = Coliseum.this.getFreeWaitingRoom();
          if (teleloc == null) {
            teleloc = Coliseum.this._zone.getRestartPoints().get(4);
          } else if ((Coliseum.this.isWaitingRoom2Free()) && (Coliseum.this.isWaitingRoom1Free()))
          {
            Coliseum.this.setPreviusWinner(null);
            for (Player member : this._party1.getPartyMembers())
            {
              if (!member.isDead())
                member.teleToClosestTown();
            }
          }
          else if (!Coliseum.this.isWaitingRoom1Free())
          {
            teleloc = Coliseum.this._zone.getRestartPoints().get(1);
            Coliseum.this.startBattle(Coliseum.this.getPartyInRoom1(), this._party1);
          }
        }
        if (this._party2.getPartyLeader().getTeam() == this._winner)
        {
          if (!Coliseum.this.getPreviusWinners().equals(this._party2))
          {
            Coliseum.this.setPreviusWinner(this._party2);
            Coliseum.this.setWinCount(1);
            for (Player member : this._party2.getPartyMembers())
              member.setFame(member.getFame() + 80, "Coliseum");
          }
          else
          {
            Coliseum.this.incWinCount();
            for (Player member : this._party2.getPartyMembers())
              member.setFame(member.getFame() + 80 + Coliseum.this.getWinCount() * 5, "Coliseum");
          }
          Location teleloc = Coliseum.this.getFreeWaitingRoom();
          if (teleloc == null) {
            teleloc = Coliseum.this._zone.getRestartPoints().get(4);
          } else if ((Coliseum.this.isWaitingRoom2Free()) && (Coliseum.this.isWaitingRoom1Free()))
          {
            Coliseum.this.setPreviusWinner(null);
            for (Player member : this._party2.getPartyMembers())
            {
              if (!member.isDead())
                member.teleToClosestTown();
            }
          }
          else if (!Coliseum.this.isWaitingRoom1Free())
          {
            teleloc = Coliseum.this._zone.getRestartPoints().get(1);
            Coliseum.this.startBattle(Coliseum.this.getPartyInRoom1(), this._party2);
          }
        }
        Coliseum.this.setIsInUse(false);
      }
    }
  }

  public class TryStart
    implements Runnable
  {
    Party _party1;
    Party _party2;

    public TryStart(Party party, Party party2)
    {
      this._party1 = party;
      this._party2 = party2;
    }

    public void run()
    {
      Coliseum.this.startBattle(this._party1, this._party2);
    }
  }
}